第 9 章:程序管理與 SELinux
程序與程式 process & program
- 程式 (program):通常為 binary program ,放置在儲存媒體中 (如硬碟、光碟、軟碟、磁帶等), 為實體檔案的型態存在
- 程序 (process):程式被觸發後,執行者的權限與屬性、程式的程式碼與所需資料等都會被載入記憶體中, 作業系統並給予這個記憶體內的單元一個識別碼 (PID),可以說,程序就是一個正在運作中的程式
子程序與父程序
當我們登入系統後,會取得一個 bash 的 shell ,然後,我們用這個 bash 提供的介面去執行另一個指令,例如 /usr/bin/passwd 或者是 touch 等等,那些另外執行的指令也會被觸發成為 PID ,那個後來執行指令才產生的 PID 就是『子程序』了,而在我們原本的 bash 環境下,就稱為『父程序』了!
所以你必須要知道,程式彼此之間是有相關性的,連續執行兩個 bash 後,第二個 bash 的父程序就是前一個 bash。因為每個程序都有一個 PID ,那某個程序的父程序該如何判斷?就透過 Parent PID (PPID) 來判斷即可。
例題:請在目前的 bash 環境下,再觸發一次 bash ,並以『 ps -l 』這個指令觀察程序相關的輸出資訊。
答:直接執行 bash ,會進入到子程序的環境中,然後輸入 ps -l 後,出現:
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 S 1000 13928 13927 0 80 0 - 29038 wait pts/0 00:00:00 bash
0 S 1000 13970 13928 1 80 0 - 29033 wait pts/0 00:00:00 bash
0 R 1000 14000 13970 0 80 0 - 30319 - pts/0 00:00:00 ps
fork and exec:程序呼叫的流程
其實子程序與父程序之間的關係還挺複雜的,最大的複雜點在於程序互相之間的呼叫。在 Linux 的程序呼叫通常稱為 fork-and-exec 的流程!程序都會藉由父程序以複製 (fork) 的方式產生一個一模一樣的子程序, 然後被複製出來的子程序再以 exec 的方式來執行 實際要進行的程式,最終就成為一個子程序的存在。
- 系統先以 fork 的方式複製一個與父程序相同的暫存程序,這個程序與父程序唯一的差別就是 PID 不同! 但是這個暫存程序還會多一個 PPID 的參數,PPID 如前所述,就是父程序的程序識別碼啦!
- 暫存程序開始以 exec 的方式載入實際要執行的程式,新的程式名稱為 qqq ,最終子程序的程式碼就會變成 qqq 了!
系統或網路服務:常駐在記憶體的程序
常駐在記憶體當中的程序通常都是負責一些系統所提供的功能以服務使用者各項任務,因此這些常駐程式就會被我們稱為:服務 (daemon)。系統的服務非常的多, 不過主要大致分成系統本身所需要的服務,例如剛剛提到的 crond 及 atd ,還有 rsyslogd 等等的。還有一些則是負責網路連線的服務,例如 Apache, named, postfix, vsftpd... 等等的。這些網路服務比較有趣的地方,在於這些程式被執行後,他會啟動一個可以負責網路監聽的埠口 (port) ,以提供外部用戶端 (client) 的連線要求。
多重登入環境的七個基本終端視窗
在 Linux 當中,預設提供了六個文字界面登入視窗,以及一個圖形界面,你可以使用 [Alt]+[F1].....[F7] 來切換不同的終端機界面,而且每個終端機界面的登入者還可以不同人! 很炫吧!這個東西可就很有用啦!尤其是在某個程序死掉的時候!
bash 環境下的工作管理 job control
我們在上一個小節有提到所謂的『父程序、子程序』的關係,那我們登入 bash 之後, 就是取得一個名為 bash 的 PID 了,而在這個環境底下所執行的其他指令, 就幾乎都是所謂的子程序了。
cp file1 file2 &
在這一串指令中,重點在那個 & 的功能,他表示將 file1 這個檔案複製為 file2 ,且放置於背景中執行, 也就是說執行這一個命令之後,在這一個終端介面仍 然可以做其他的工作!而當這一個指令 (cp file1 file2) 執行完畢之後,系統將會在你的終端介面顯示完成的消息!很便利喔!
工作管理 job control
這個工作管理 (job control) 是用在 bash 環境下的,也就是說:『當我們登入系統取得 bash shell 之後,在單一終端機介面下同時進行多個工作的行為管理 』。舉例來說,我們在登入 bash 後, 想要一邊複製檔案、一邊進行資料搜尋、一邊進行編譯,還可以一邊進行 vim 程式撰寫!
什麼是工作管理
進行工作管理的行為中, 其實每個工作都是目前 bash 的子程序,亦即彼此之間是有相關性的。 我們無法以 job control 的方式由 tty1 的環境去管理 tty2 的 bash !
既然我可以在六個終端介面登入,那何必使用 job control 呢? 真是脫褲子放屁,多此一舉啊!不要忘記了呢,我們可以設定使用者同時可以登入的連線數,在這樣的情況下,某些使用者可能僅能以一個連線來工作呢! 所以囉,你就得要瞭解一下這種工作管理的模式了!
由於假設我們只有一個終端介面,因此在可以出現提示字元讓你操作的環境就稱為前景 (foreground),至於其他工作就可以讓你放入背景 (background) 去暫停或運作。要注意的是,放入背景的工作想要運作時, 他必須不能夠與使用者互動。舉例來說, vim 絕對不可能在背景裡面執行 (running) 的!因為你沒有 輸入資料他就不會跑啊! 而且放入背景的工作是不可以使用 [ctrl]+c 來終止的!
總之,要進行 bash 的 job control 必須要注意到的限制是:
- 這些工作所觸發的程序必須來自於你 shell 的子程序(只管理自己的 bash);
- 前景:你可以控制與下達指令的這個環境稱為前景的工作 (foreground);
- 背景:可以自行運作的工作,你無法使用 [ctrl]+c 終止他,可使用 bg/fg 呼叫該工作;
- 背景中『執行』的程序不能等待 terminal/shell 的輸入(input)
job control 的管理
如前所述,bash 只能夠管理自己的工作而不能管理其他 bash 的工作,所以即使你是 root 也不能夠將別人的 bash 底下的 job 給他拿過來執行。此外,又分前景與背景,然後在背景裡面的工作狀態又可以分為『暫停 (stop)』與『運作中 (running)』。那實際進行 job 控制的指令有哪些?底下就來談談。
直接將指令丟到背景中『執行』的 &
如同前面提到的,我們在只有一個 bash 的環境下,如果想要同時進行多個工作, 那麼可以將某些工作直接丟到背景環境當中,讓我們可以繼續操作前景的工作!那麼如何將工作丟到背景中? 最簡單的方法就是利用『 & 』這個玩意兒了!舉個簡單的例子,我們要將 /etc/ 整個備份成為 /tmp/etc.tar.gz 且不想要等待,那麼可以這樣做
備份至 /tmp/etc.tar.gz
tar -zpcf /tmp/etc.tar.gz /etc &
[1] 14432 <== [job number] PID
tar: Removing leading `/' from member names
# 在中括號內的號碼為工作號碼 (job number),該號碼與 bash 的控制有關。
# 後續的 14432 則是這個工作在系統中的 PID。至於後續出現的資料是 tar 執行的資料流,
# 由於我們沒有加上資料流重導向,所以會影響畫面!不過不會影響前景的操作喔!
仔細的瞧一瞧,我在輸入一個指令後,在該指令的最後面加上一個『 & 』代表將該指令丟到背景中, 此時 bash 會給予這個指令一個『工作號碼(job number)』,就是那個 [1] 啦!至於後面那個 14432 則是該指令所觸發的『 PID 』了!而且,有趣的是,我們可以繼續操作 bash 呢!很不賴吧! 不過,那麼丟到背景中的工作什麼時候完成?完成的時候會顯示什麼?如果你輸入幾個指令後,突然出現這個資料:
[1]+ Done tar -zpcf /tmp/etc.tar.gz /etc
就代表 [1] 這個工作已經完成 (Done) ,該工作的指令則是接在後面那一串指令列。 這樣瞭解了吧!另外,這個 & 代表:『將工作丟到背景中去執行』喔! 注意到那個『執行』的字眼!此外,這樣的情況最大的好處是: 不怕被 [ctrl]+c 中斷的啦! 此外,將工作丟到背景當中要特別注意資料的流向喔!包括上面的訊息就有出現錯誤訊息,導致我的前景被影響。 雖然只要按下 [enter] 就會出現提示字元。但如果我將剛剛那個指令改成:
tar -zpcvf /tmp/etc.tar.gz /etc &
情況會怎樣?在背景當中執行的指令,如果有 stdout 及 stderr 時,他的資料依舊是輸出到螢幕上面的, 所以,我們會無法看到提示字元,當然也就無法完好的掌握前景工作。同時由於是背景工作的 tar , 此時你怎麼按下 [ctrl]+c 也無法停止螢幕被搞的花花綠綠的!所以囉,最佳的狀況就是利用資料流重導向, 將輸出資料傳送至某個檔案中。舉例來說,我可以這樣做:
tar -zpcvf /tmp/etc.tar.gz /etc > /tmp/log.txt 2>&1 &
[1] 14547
將『目前』的工作丟到背景中『暫停』:[ctrl]-z
想個情況:如果我正在使用 vim ,卻發現我有個檔案不知道放在哪裡,需要到 bash 環境下進行搜尋,此時是否要結束 vim 呢?只要暫時將 vim 給他丟到背景當中等待即可。 例如以下的案例
將目前的工作丟到背景中暫停
vim ~/.bashrc
# 在 vim 的一般模式下,按下 [ctrl]-z 這兩個按鍵
[1]+ Stopped vim ~/.bashrc
<==順利取得了前景的操控權!
find / -print....(輸出省略)....
# 此時螢幕會非常的忙碌!因為螢幕上會顯示所有的檔名。請按下 [ctrl]-z 暫停
[2]+ Stopped find / -print
在 vim 的一般模式下,按下 [ctrl] 及 z 這兩個按鍵,螢幕上會出現 [1] ,表示這是第一個工作, 而那個 + 代表最近一個被丟進背景的工作,且目前在背景下預設會被取用的那個工作 (與 fg 這個指令有關 )!而那個 Stopped 則代表目前這個工作的狀態。在預設的情況下,使用 [ctrl]-z 丟到背景當中的工作都是『暫停』的狀態喔!
jobs 觀察目前的背景工作狀態
jobs 觀察目前的背景工作狀態
jobs [-lrs]
選項與參數:
-l :除了列出 job number 與指令串之外,同時列出 PID 的號碼;
-r :僅列出正在背景 run 的工作;
-s :僅列出正在背景當中暫停 (stop) 的工作。範例一:觀察目前的 bash 當中,所有的工作,與對應的 PID
jobs -l
[1]- 14566 Stopped vim ~/.bashrc
[2]+ 14567 Stopped find / -print
如果想要知道目前有多少的工作在背景當中,就用 jobs 這個指令吧!一般來說,直接下達 jobs 即可! 不過,如果你還想要知道該 job number 的 PID 號碼,可以加上 -l 這個參數啦! 在輸出的資訊當中,例如上表,仔細看到那個 + - 號喔!那個 + 代表預設的取用工作。 所以說:『目前我有兩個工作在背景當中,兩個工作都是暫停的, 而如果我僅輸入 fg 時,那麼那個 [2] 會被拿到前景當中來處理』!
其實 + 代表最近被放到背景的工作號碼, - 代表最近最後第二個被放置到背景中的工作號碼。 而超過最後第三個以後的工作,就不會有 +/- 符號存在了!
fg 將背景工作拿到前景來處理
剛剛提到的都是將工作丟到背景當中去執行的,那麼有沒有可以將背景工作拿到前景來處理的? 有啊!就是那個 fg (foreground) 啦!舉例來說,我們想要將上頭範例當中的工作拿出來處理時:
fg 將背景工作拿到前景來處理
fg %jobnumber
選項與參數:
%jobnumber :jobnumber 為工作號碼(數字)。注意,那個 % 是可有可無的!範例一:先以 jobs 觀察工作,再將工作取出:
jobs -l
[1]- 14566 Stopped vim ~/.bashrc
[2]+ 14567 Stopped find / -print
fg <==預設取出那個 + 的工作,亦即 [2]。立即按下[ctrl]-z
fg %1 <==直接規定取出的那個工作號碼!再按下[ctrl]-z
jobs -l
[1]+ 14566 Stopped vim ~/.bashrc
[2]- 14567 Stopped find / -print
經過 fg 指令就能夠將背景工作拿到前景來處理囉!不過比較有趣的是最後一個顯示的結果,我們會發現 + 出現在第一個工作後! 怎麼會這樣啊?這是因為你剛剛利用 fg %1 將第一號工作捉到前景後又放回背景,此時最後一個被放入背景的將變成 vi 那個指令動作, 所以當然 [1] 後面就會出現 + 了!瞭解乎!另外,如果輸入『 fg - 』 則代表將 - 號的那個工作號碼拿出來,上面就是 [2]- 那個工作號碼啦!
bg 讓工作在背景下的狀態變成運作中
我們剛剛提到,那個 [ctrl]-z 可以將目前的工作丟到背景底下去『暫停』, 那麼如何讓一個工作在背景底下『 Run 』呢?我們可以在底下這個案例當中來測試!
bg 讓工作在背景下的狀態變成運作中
範例一:一執行 find / -perm /7000 > /tmp/text.txt 後,立刻丟到背景去暫停!
find / -perm /7000 > /tmp/text.txt# 此時,請立刻按下 [ctrl]-z 暫停!
[3]+ Stopped find / -perm /7000 > /tmp/text.txt
範例二:讓該工作在背景下進行,並且觀察他!!
jobs ; bg %3 ; jobs
[1] Stopped vim ~/.bashrc
[2]- Stopped find / -print
[3]+ Stopped find / -perm /7000 > /tmp/text.txt
[3]+ find / -perm /7000 > /tmp/text.txt &
[1]- Stopped vim ~/.bashrc
[2]+ Stopped find / -print
[3] Running find / -perm /7000 > /tmp/text.txt &
kill 管理背景當中的工作
剛剛我們可以讓一個已經在背景當中的工作繼續工作,也可以讓該工作以 fg 拿到前景來, 那麼,如果想要將該工作直接移除呢?或者是將該工作重新啟動呢?這個時候就得需要給予該工作一個訊號 (signal) ,讓他知道該怎麼作才好啊!此時, kill 這個指令就派上用場啦!
kill 管理背景當中的工作
kill -signal %jobnumber
kill -l
選項與參數:
-l :這個是 L 的小寫,列出目前 kill 能夠使用的訊號 (signal) 有哪些?
signal :代表給予後面接的那個工作什麼樣的指示囉!用 man 7 signal 可知:
-1 :重新讀取一次參數的設定檔 (類似 reload);
-2 :代表與由鍵盤輸入 [ctrl]-c 同樣的動作;
-9 :立刻強制刪除一個工作;
-15:以正常的程序方式終止一項工作。與 -9 是不一樣的。範例一:找出目前的 bash 環境下的背景工作,並將該工作『強制刪除』。
jobs
[1]+ Stopped vim ~/.bashrc
[2] Stopped find / -print
kill -9 %2; jobs
[1]+ Stopped vim ~/.bashrc
[2] Killed find / -print
# 再過幾秒你再下達 jobs 一次,就會發現 2 號工作不見了!因為被移除了!範例二:找出目前的 bash 環境下的背景工作,並將該工作『正常終止』掉。
jobs
[1]+ Stopped vim ~/.bashrc
kill -SIGTERM %1# -SIGTERM 與 -15 是一樣的!您可以使用 kill -l 來查閱!
# 不過在這個案例中, vim 的工作無法被結束喔!因為他無法透過 kill 正常終止的意思!
特別留意一下, -9 這個 signal 通常是用在『強制刪除一個不正常的工作』時所使用的, -15 則是以正常步驟結束一項工作(15也是預設值),兩者之間並不相同呦!舉上面的例子來說, 我用 vim 的時候,不是會產生一個 .filename.swp 的檔案嗎? 那麼,當使用 -15 這個 signal 時, vim 會嘗試以正常的步驟來結束掉該 vi 的工作, 所以 .filename.swp 會主動的被移除。但若是使用 -9 這個 signal 時,由於該 vim 工作會被強制移除掉,因此, .filename.swp 就會繼續存在檔案系統當中。
nohup 離線管理問題
要注意的是,我們在工作管理當中提到的『背景』指的是在終端機模式下可以避免 [ctrl]-c 中斷的一個情境, 你可以說那個是 bash 的背景,並不是放到系統的背景去喔!所以,工作管理的背景依舊與終端機有關啦! 在這樣的情況下,如果你是以遠端連線方式連接到你的 Linux 主機,並且將工作以 & 的方式放到背景去, 請問,在工作尚未結束的情況下你離線了,該工作還會繼續進行嗎?答案是『否』!不會繼續進行,而是會被中斷掉。
那怎麼辦?如果我的工作需要進行一大段時間,我又不能放置在背景底下,那該如何處理呢? 首先,你可以參考前一章的 at 來處理即可!因為 at 是將工作 放置到系統背景, 而與終端機無關。如果不想要使用 at 的話,那你也可以嘗試使用 nohup 這個指令來處理喔!這個 nohup 可以讓你在離線或登出系統後,還能夠讓工作繼續進行。他的語法有點像這樣:
nohup 離線管理
nohup [指令與參數] <==在終端機前景中工作
nohup [指令與參數] & <==在終端機背景中工作
有夠好簡單的指令吧!上述指令需要注意的是, nohup 並不支援 bash 內建的指令,因此你的指令必須要是外部指令才行。 我們來嘗試玩一下底下的任務吧!
# 1. 先編輯一支會『睡著 500 秒』的程式:
vim sleep500.sh
#!/bin/bash
/bin/sleep 500s
/bin/echo "I have slept 500 seconds."
# 2. 丟到背景中去執行,並且立刻登出系統:
chmod a+x sleep500.sh
nohup ./sleep500.sh &
[2] 14812
nohup: ignoring input and appending output to `nohup.out' <==會告知這個訊息!
exit
如果你再次登入的話,再使用 pstree 去查閱你的程序,會發現 sleep500.sh 還在執行中喔!並不會被中斷掉! 這樣瞭解意思了嗎?由於我們的程式最後會輸出一個訊息,但是 nohup 與終端機其實無關了, 因此這個訊息的輸出就會被導向『 ~/nohup.out 』,所以你才會看到上述指令中,當你輸入 nohup 後, 會出現那個提示訊息囉。
如果你想要讓在背景的工作在你登出後還能夠繼續的執行,那麼使用 nohup 搭配 & 是不錯的運作情境喔! 可以參考看看!
ps 程序管理
將某個時間點的程序運作情況擷取下來
ps 程序管理
ps aux:觀察系統所有的程序資料
ps -lA:也是能夠觀察所有系統的資料
ps axjf:連同部分程序樹狀態
選項與參數:
-A :所有的 process 均顯示出來,與 -e 具有同樣的效用;
-a :不與 terminal 有關的所有 process ;
-u :有效使用者 (effective user) 相關的 process ;
x :通常與 a 這個參數一起使用,可列出較完整資訊。
輸出格式規劃:
l :較長、較詳細的將該 PID 的的資訊列出;
j :工作的格式 (jobs format)
-f :做一個更為完整的輸出。
- 僅觀察自己的 bash 相關程序: ps -l
範例一:將目前屬於您自己這次登入的 PID 與相關資訊列示出來(只與自己的 bash 有關)
ps -lF S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 14830 13970 0 80 0 - 52686 poll_s pts/0 00:00:00 sudo
4 S 0 14835 14830 0 80 0 - 50511 wait pts/0 00:00:00 su
4 S 0 14836 14835 0 80 0 - 29035 wait pts/0 00:00:00 bash
0 R 0 15011 14836 0 80 0 - 30319 - pts/0 00:00:00 ps
# 還記得鳥哥說過,非必要不要使用 root 直接登入吧?從這個 ps -l 的分析,你也可以發現,
# 鳥哥其實是使用 sudo 才轉成 root 的身份~否則連測試機,鳥哥都是使用一般帳號登入的!
- F:代表這個程序旗標 (process flags),說明這個程序的總結權限,常見號碼有:
- 若為 4 表示此程序的權限為 root ;
- 若為 1 則表示此子程序僅進行複製(fork)而沒有實際執行(exec)。
- S:代表這個程序的狀態 (STAT),主要的狀態有:
- R (Running):該程式正在運作中;
- S (Sleep):該程式目前正在睡眠狀態(idle),但可以被喚醒(signal)。
- D :不可被喚醒的睡眠狀態,通常這支程式可能在等待 I/O 的情況(ex>列印)
- T :停止狀態(stop),可能是在工作控制(背景暫停)或除錯 (traced) 狀態;
- Z (Zombie):僵屍狀態,程序已經終止但卻無法被移除至記憶體外。
- UID/PID/PPID:代表『此程序被該 UID 所擁有/程序的 PID 號碼/此程序的父程序 PID 號碼』
- C:代表 CPU 使用率,單位為百分比;
- PRI/NI:Priority/Nice 的縮寫,代表此程序被 CPU 所執行的優先順序,數值越小代表該程序越快被 CPU 執行。詳細的 PRI 與 NI 將在下一小節說明。
- ADDR/SZ/WCHAN:都與記憶體有關,ADDR 是 kernel function,指出該程序在記憶體的哪個部分,如果是個 running 的程序,一般就會顯示『 - 』 / SZ 代表此程序用掉多少記憶體 / WCHAN 表示目前程序是否運作中,同樣的, 若為 - 表示正在運作中。
- TTY:登入者的終端機位置,若為遠端登入則使用動態終端介面 (pts/n);
- TIME:使用掉的 CPU 時間,注意,是此程序實際花費 CPU 運作的時間,而不是系統時間;
- CMD:就是 command 的縮寫,造成此程序的觸發程式之指令為何。
- 觀察系統所有程序: ps aux
範例二:列出目前所有的正在記憶體當中的程序:
ps auxUSER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.2 60636 7948 ? Ss Aug04 0:01 /usr/lib/systemd/systemd ...
root 2 0.0 0.0 0 0 ? S Aug04 0:00 [kthreadd]
.....(中間省略).....
root 14830 0.0 0.1 210744 3988 pts/0 S Aug04 0:00 sudo su -
root 14835 0.0 0.1 202044 2996 pts/0 S Aug04 0:00 su -
root 14836 0.0 0.1 116140 2960 pts/0 S Aug04 0:00 -bash
.....(中間省略).....
root 18459 0.0 0.0 123372 1380 pts/0 R+ 00:25 0:00 ps aux
項目 | 描述 |
---|---|
USER | 該 process 屬於那個使用者帳號的 |
PID | 該 process 的程序識別碼 |
%CPU | 該 process 使用掉的 CPU 資源百分比 |
%MEM | 該 process 所佔用的實體記憶體百分比 |
VSZ | 該 process 使用掉的虛擬記憶體量 (Kbytes) |
RSS | 該 process 佔用的固定的記憶體量 (Kbytes) |
TTY | 該 process 是在那個終端機上面運作,若與終端機無關則顯示 ?,另外, tty1-tty6 是本機上面的登入者程序,若為 pts/0 等等的,則表示為由網路連接進主機的程序 |
STAT | 該程序目前的狀態,狀態顯示與 ps -l 的 S 旗標相同 (R/S/T/Z) |
START | 該 process 被觸發啟動的時間 |
TIME | 該 process 實際使用 CPU 運作的時間 |
COMMAND | 該程序的實際指令為何 |
範例三:以範例一的顯示內容,顯示出所有的程序:
ps -lA
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 1 0 0 80 0 - 15159 ep_pol ? 00:00:01 systemd
1 S 0 2 0 0 80 0 - 0 kthrea ? 00:00:00 kthreadd
1 S 0 3 2 0 80 0 - 0 smpboo ? 00:00:00 ksoftirqd/0
....(以下省略)....
# 你會發現每個欄位與 ps -l 的輸出情況相同,但顯示的程序則包括系統所有的程序。範例四:列出類似程序樹的程序顯示:
ps axjf
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
0 2 0 0 ? -1 S 0 0:00 [kthreadd]
2 3 0 0 ? -1 S 0 0:00 \_ [ksoftirqd/0]
.....(中間省略).....
1 1326 1326 1326 ? -1 Ss 0 0:00 /usr/sbin/sshd -D
1326 13923 13923 13923 ? -1 Ss 0 0:00 \_ sshd: dmtsai [priv]
13923 13927 13923 13923 ? -1 S 1000 0:00 \_ sshd: dmtsai@pts/0
13927 13928 13928 13928 pts/0 18703 Ss 1000 0:00 \_ -bash
13928 13970 13970 13928 pts/0 18703 S 1000 0:00 \_ bash
13970 14830 14830 13928 pts/0 18703 S 0 0:00 \_ sudo su -
14830 14835 14830 13928 pts/0 18703 S 0 0:00 \_ su -
14835 14836 14836 13928 pts/0 18703 S 0 0:00 \_ -bash
14836 18703 18703 13928 pts/0 18703 R+ 0 0:00 \_ ps axjf
.....(後 面省略).....
範例五:找出與 cron 與 rsyslog 這兩個服務有關的 PID 號碼?
ps aux | egrep '(cron|rsyslog)'
root 742 0.0 0.1 208012 4088 ? Ssl Aug04 0:00 /usr/sbin/rsyslogd -n
root 1338 0.0 0.0 126304 1704 ? Ss Aug04 0:00 /usr/sbin/crond -n
root 18740 0.0 0.0 112644 980 pts/0 S+ 00:49 0:00 grep -E --color=auto (cron|rsyslog)
# 所以號碼是 742 及 1338 這兩個囉!就是這樣找的啦!
除此之外,我們必須要知道的是『僵屍 (zombie) 』程序是什麼? 通常,造成僵屍程序的成因是因為該程序應該已經執行完畢,或者是因故應該要終止了, 但是該程序的父程序卻無法完整的將該程序結束掉,而造成那個程序一直存在記憶體當中。 如果你發現在某個程序的 CMD 後面還接上 <defunct>
時,就代表該程序是僵屍程序啦,例如:
apache 8683 0.0 0.9 83384 9992 ? Z 14:33 0:00 /usr/sbin/httpd <defunct>
當系統不穩定的時候就容易造成所謂的僵屍程序,可能是因為程式寫的不好啦,或者是使用者的操作習慣不良等等所造成。 如果你發現系統中很多僵屍程序時,記得啊!要找出該程序的父程序,然後好好的做個追蹤,好好的進行主機的環境最佳化啊! 看看有什麼地方需要改善的,不要只是直接將他 kill 掉而已呢!不然的話,萬一他一直產生,那可就麻煩了! @_@
事實上,通常僵屍程序都已經無法控管,而直接是交給 systemd 這支程式來負責了,偏偏 systemd 是系統第一支執行的程式, 他是所有程式的父程式!我們無法殺掉該程式的 (殺掉他,系統就死掉了!),所以囉,如果產生僵屍程序, 而系統過一陣子還沒有辦法透過核心非經常性的特殊處理來將該程序刪除時,那你只好透過 reboot 的方式來將該程序抹去了!
top 動態觀察程序的變化
top
top [-d 數字] | top [-bnp]
選項與參數:
-d :後面可以接秒數,就是整個程序畫面更新的秒數。預設是 5 秒;
-b :以批次的方式執行 top ,還有更多的參數可以使用喔!
通常會搭配資料流重導向來將批次的結果輸出成為檔案。
-n :與 -b 搭配,意義是,需要進行幾次 top 的輸出結果。
-p :指定某些個 PID 來進行觀察監測而已。
在 top 執行過程當中可以使用的按鍵指令:
? :顯示在 top 當中可以輸入的按鍵指令;
P :以 CPU 的使用資源排序顯示;
M :以 Memory 的使用資源排序顯示;
N :以 PID 來排序喔!
T :由該 Process 使用的 CPU 時間累積 (TIME+) 排序。
k :給予某個 PID 一個訊號 (signal)
r :給予某個 PID 重新制訂一個 nice 值。
q :離開 top 軟體的按鍵。
範例一:每兩秒鐘更新一次 top ,觀察整體資訊:
top -d 2
top - 00:53:59 up 6:07, 3 users, load average: 0.00, 0.01, 0.05
Tasks: 179 total, 2 running, 177 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 2916388 total, 1839140 free, 353712 used, 723536 buff/cache
KiB Swap: 1048572 total, 1048572 free, 0 used. 2318680 avail Mem
<==如果加入 k 或 r 時,就會有相關的字樣出現在這裡喔!
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
18804 root 20 0 130028 1872 1276 R 0.5 0.1 0:00.02 top
1 root 20 0 60636 7948 2656 S 0.0 0.3 0:01.70 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.01 kthreadd
3 root 20 0 0 0 0 S 0.0 0.0 0:00.00 ksoftirqd/0
- 第一行(top...):這一行顯示的資訊分別為:
- 目前的時間,亦即是 00:53:59 那個項目;
- 開 機到目前為止所經過的時間,亦即是 up 6:07, 那個項目;
- 已經登入系統的使用者人數,亦即是 3 users, 項目;
- 系統在 1, 5, 15 分鐘的平均工作負載。我們在第十五章談到的 batch 工作方式為負載小於 0.8 就是這個負載囉!代表的是 1, 5, 15 分鐘,系統平均要負責運作幾個程序(工作)的意思。 越小代表系統越閒置,若高於 1 得要注意你的系統程序是否太過繁複了!
- 第二行(Tasks...):顯示的是目前程序的總量與個別程序在什麼狀態(running, sleeping, stopped, zombie)。 比較需要注意的是最後的 zombie 那個數值,如果不是 0 !好好看看到底是那個 process 變成僵屍了吧?
- 第三行(%Cpus...):顯示的是 CPU 的整體負載,每個項目可使用 ? 查閱。需要特別注意的是 wa 項目,那個項目代表的是 I/O wait, 通常你的系統會變慢都是 I/O 產生的問題比較大!因此這裡得要注意這個項目耗用 CPU 的資源喔! 另外,如果是多核心的設備,可以按下數字鍵『1』來切換成不同 CPU 的負載率。
- 第四行與第五行:表示目前的實體記憶體與虛擬記憶體 (Mem/Swap) 的使用情況。 再次重申,要注意的是 swap 的使用量要盡量的少!如果 swap 被用的很大量,表示系統的實體記憶體實在不足!
- 第六行:這個是當在 top 程式當中輸入指令時,顯示狀態的地方。
至於 top 下半部分的畫面,則是每個 process 使用的資源情況。比較需要注意的是:
項目 | 描述 |
---|---|
PID | 每個 process 的 ID |
USER | 該 process 所屬的使用者 |
PR | Priority 的簡寫,程序的優先執行順序,越小越早被執行 |
NI | Nice 的簡寫,與 Priority 有關,也是越小越早被執行 |
%CPU | CPU 的使用率 |
%MEM | 記憶體的使用率 |
TIME+ | CPU 使用時間的累加 |
範例二:將 top 的資訊進行 2 次,然後將結果輸出到 /tmp/top.txt
top -b -n 2 > /tmp/top.txt# 這樣一來,嘿嘿!就可以將 top 的資訊存到 /tmp/top.txt 檔案中了。
範例三:我們自己的 bash PID 可由 $$ 變數取得,請使用 top 持續觀察該 PID
echo $$
14836 <==就是這個數字!他是我們 bash 的 PID
top -d 2 -p 14836
top - 01:00:53 up 6:14, 3 users, load average: 0.00, 0.01, 0.05
Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.1 sy, 0.0 ni, 99.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 2916388 total, 1839264 free, 353424 used, 723700 buff/cache
KiB Swap: 1048572 total, 1048572 free, 0 used. 2318848 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
14836 root 20 0 116272 3136 1848 S 0.0 0.1 0:00.07 bash
範例四:承上題,上面的 NI 值是 0 ,想要改成 10 的話?
# 在範例三的 top 畫面當中直接按下 r 之後,會出現如下的圖樣!
top - 01:02:01 up 6:15, 3 users, load average: 0.00, 0.01, 0.05
Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.1 us, 0.0 sy, 0.0 ni, 99.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 2916388 total, 1839140 free, 353576 used, 723672 buff/cache
KiB Swap: 1048572 total, 1048572 free, 0 used. 2318724 avail Mem
PID to renice [default pid = 14836]14836 PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
14836 root 20 0 116272 3136 1848 S 0.0 0.1 0:00.07 bash
Renice PID 14836 to value10 <==這是 nice 值
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
top - 01:04:13 up 6:17, 3 users, load average: 0.00, 0.01, 0.05
Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 2916388 total, 1838676 free, 354020 used, 723692 buff/cache
KiB Swap: 1048572 total, 1048572 free, 0 used. 2318256 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
14836 root 30 10 116272 3136 1848 S 0.0 0.1 0:00.07 bash
pstree 尋找程序相關性
pstree
pstree [-A|U] [-up]
選項與參數:
-A :各程序樹之間的連接以 ASCII 字元來連接;
-U :各程序樹之間的連接以萬國碼的字元來連接。在某些終端介面下可能會有錯誤;
-p :並同時列出每個 process 的 PID;
-u :並同時列出每個 process 的所屬帳號名稱。範例一:列出目前系統上面所有的程序樹的相關性:
pstree -A
systemd-+-ModemManager---2*[{ModemManager}] # 這行是 ModenManager 與其子程序
|-NetworkManager---3*[{NetworkManager}] # 前面有數字,代表子程序的數量!
....(中間省略)....
|-sshd---sshd---sshd---bash---bash---sudo---su---bash---pstree <==我們指令執行的相依性
....(底下省略)....# 注意一下,為了節省版面,所以鳥哥已經刪去很多程序了!範例二:承上題,同時秀出 PID 與 users
pstree -Aup
systemd(1)-+-ModemManager(745)-+-{ModemManager}(785)
| `-{ModemManager}(790)
|-NetworkManager(870)-+-{NetworkManager}(907)
| |-{NetworkManager}(911)
| `-{NetworkManager}(914)
....(中間省略)....
|-sshd(1326)---sshd(13923)---sshd(13927,dmtsai)---bash(13928)---bash(13970)---
....(底下省略)....# 在括號 () 內的即是 PID 以及該程序的 owner 喔!一般來說,如果該程序的所有人與父程序同,
# 就不會列出,但是如果與父程序不一樣,那就會列出該程序的擁有者!看上面 13927 就轉變成 dmtsai 了
如果要找程序之間的相關性,這個 pstree 真是好用到不行!直接輸入 pstree 可以查到程序相關性,如上表所示,還會使用線段將相關性程序連結起來哩! 一般連結符號可以使用 ASCII 碼即可,但有時因為語系問題會主動的以 Unicode 的符號來連結, 但因為可能終端機無法支援該編碼,或許會造成亂碼問題。因此可以加上 -A 選項來克服此類線段亂碼問題。
由 pstree 的輸出我們也可以很清楚的知道,所有的程序都是依附在 systemd 這支程序底下的! 仔細看一下,這支程序的 PID 是一號喔!因為他是由 Linux 核心所主動呼叫的第一支程式!所以 PID 就是一號了。 這也是我們剛剛提到僵屍程序時有提到,為啥發生僵屍程序需要重新開機? 因為 systemd 要重新啟動,而重新啟動 systemd 就是 reboot 囉!
程序的管理
程序之間是可以互相控制的!舉例來說,你可以關閉、重新啟動伺服器軟體,伺服器軟體本身是個程序, 你既然可以讓她關閉或啟動,當然就是可以控制該程序啦!那麼程序是如何互相管理的呢?其實是透過給予該程序一個訊號 (signal) 去告知該程序你想要讓她作什麼!因此這個訊號就很重要啦!
要給予某個已經存在背景中的工作某些動作時,是直接給予一個訊號給該工作號碼即可。那麼到底有多少 signal 呢? 你可以使用 kill -l (小寫的 L ) 或者是 man 7 signal 都可以查詢到!主要的訊號代號與名稱對應及內容是:
代號 | 名稱 | 內容 |
---|---|---|
1 | SIGHUP | 啟動被終止的程序,可讓該 PID 重新讀取自己的設定檔,類似重新啟動 |
2 | SIGINT | 相當於用鍵盤輸入 [ctrl]-c 來中斷一個程序的進行 |
9 | SIGKILL | 代表強制中斷一個程序的進行,如果該程序進行到一半, 那麼尚未完成的部分可能會有『半產品』產生,類似 vim會有 .filename.swp 保留下來。 |
15 | SIGTERM | 以正常的結束程序來終止該程序。由於是正常的終止, 所以後續的動作會將他完成。不過,如果該程序已經發生問題,就是無法使用正常的方法終止時, 輸入這個 signal 也是沒有用的。 |
19 | SIGSTOP | 相當於用鍵盤輸入 [ctrl]-z 來暫停一個程序的進行 |
上面僅是常見的 signal 而已,更多的訊號資訊請自行 man 7 signal 吧!一般來說,你只要記得『1, 9, 15』這三個號碼的意義即可。那麼我們如何傳送一個訊號給某個程序呢?就透過 kill 或 killall 吧!底下分別來看看:
kill -signal PID
kill 可以幫我們將這個 signal 傳送給某個工作 (%jobnumber) 或者是某個 PID (直接輸入數字)。 要再次強調的是: kill 後面直接加數字與加上 %number 的情況是不同的! 這個很重要喔!因為工作控制中有 1 號工作,但是 PID 1 號則是專指『 systemd 』這支程式!你怎麼可以將 systemd 關閉呢? 關閉 systemd ,你的系統就當掉了啊!所以記得那個 % 是專門用在工作控制的喔! 我們就活用一下 kill 與剛剛上面提到的 ps 來做個簡單的練習吧!
例題:以 ps 找出 rsyslogd 這個程序的 PID 後,再使用 kill 傳送訊息,使得 rsyslogd 可以重新讀取設定檔。
答:由於需要重新讀取設定檔,因此 signal 是 1 號。至於找出 rsyslogd 的 PID 可以是這樣做
kill -signal PID
ps aux | grep 'rsyslogd' | grep -v 'grep'| awk '{print $2}'
接下來則是實際使用 kill -1 PID,因此,整串指令會是這樣
kill -SIGHUP $(ps aux | grep 'rsyslogd' | grep -v 'grep'| awk '{print $2}')
如果要確認有沒有重新啟動 syslog ,可以參考登錄檔的內容,使用如下指令查閱:tail -5 /var/log/messages如果你有看到類似『Aug 5 01:25:02 study rsyslogd: [origin software="rsyslogd" swVersion="7.4.7" x-pid="742" x-info="http://www.rsyslog.com"] rsyslogd was HUPed』之類的字樣,就是表示 rsyslogd 在 8/5 有重新啟動 (restart) 過了!
瞭解了這個用法以後,如果未來你想要將某個莫名其妙的登入者的連線刪除的話,就可以透過使用 pstree -p 找到相關程序, 然後再以 kill -9 將該程序刪除,該條連線就會被踢掉了!這樣很簡單吧!
killall -signal 指令名稱
由於 kill 後面必須要加上 PID (或者是 job number),所以,通常 kill 都會配合 ps, pstree 等指令,因為我們必須要找到相對應的那個程序的 ID 嘛!但是,如此一來,很麻煩~有沒有可以利用『下達指令的名稱』來給予訊號的?舉例來說,能不能直接將 rsyslogd 這個程序給予一個 SIGHUP 的訊號呢?可以的!用 killall 吧!
killall -signal 指令名稱
killall [-iIe] [command name]
選項與參數:
-i :interactive 的意思,互動式的,若需要刪除時,會出現提示字元給使用者;
-e :exact 的意思,表示『後面接的 command name 要一致』,但整個完整的指令
不能超過 15 個字元。
-I :指令名稱(可能含參數)忽略大小寫。範例一:給予 rsyslogd 這個指令啟動的 PID 一個 SIGHUP 的訊號
killall -1 rsyslogd# 如果用 ps aux 仔細看一下,若包含所有參數,則 /usr/sbin/rsyslogd -n 才是最完整的!範例二:強制終止所有以 httpd 啟動的程序 (其實並沒有此程序在系統內)
killall -9 httpd範例三:依次詢問每個 bash 程式是否需要被終止運作!
killall -i -9 bash
Signal bash(13888) ? (y/N)n <==這個不殺!
Signal bash(13928) ? (y/N)n <==這個不殺!
Signal bash(13970) ? (y/N)n <==這個不殺!
Signal bash(14836) ? (y/N)y <==這個殺掉!
# 具有互動的功能!可以詢問你是否要刪除 bash 這個程式。要注意,若沒有 -i 的參數,
# 所有的 bash 都會被這個 root 給殺掉!包括 root 自己的 bash 喔! ^_^
關於程序的執行順序 Priority 與 Nice 值
ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 14836 14835 0 90 10 - 29068 wait pts/0 00:00:00 bash
0 R 0 19848 14836 0 90 10 - 30319 - pts/0 00:00:00 ps
# 你應該要好奇,怎麼我的 NI 已經是 10 了?還記得剛剛 top 的測試嗎?我們在那邊就有改過一次喔!
由於 PRI 是核心動態調整的,我們使用者也無權去干涉 PRI !那如果你想要調整程序的優先執行序時,就得要透過 Nice 值了!Nice 值就是上表的 NI 啦!一般來說, PRI 與 NI 的相關性如下:
PRI(new) = PRI(old) + nice
不過你要特別留意到,如果原本的 PRI 是 50 ,並不是我們給予一個 nice = 5 ,就會讓 PRI 變成 55 喔! 因為 PRI 是系統『動態』決定的,所以,雖然 nice 值是可以影響 PRI ,不過, 最終的 PRI 仍是要經過系統分析後才會決定的。另外, nice 值是有正負的喔,而既然 PRI 越小越早被執行, 所以,當 nice 值為負值時,那麼該程序就會降低 PRI 值,亦即會變的較優先被處理。此外,你必須要留意到:
- nice 值可調整的範圍為 -20 ~ 19 ;
- root 可隨意調整自己或他人程序的 Nice 值,且範圍為 -20 ~ 19 ;
- 一般使用者僅可調整自己程序的 Nice 值,且範圍僅為 0 ~ 19 (避免一般用戶搶佔系統資源);
- 一般使用者僅可將 nice 值越調越高,例如本來 nice 為 5 ,則未來僅能調整到大於 5;
這也就是說,要調整某個程序的優先執行序,就是『調整該程序的 nice 值』啦!那麼如何給予某個程序 nice 值呢?有兩種方式,分別是:
- 一開始執行程式就立即給予一個特定的 nice 值:用 nice 指令;
- 調整某個已經存在的 PID 的 nice 值:用 renice 指令。
nice :新執行的指令即給予新的 nice 值
nice
nice [-n 數字] command
選項與參數:
-n :後面接一個數值,讓原本的 nice 加上這個新的數值之意。修改後的最終數值的範圍則為 -20 ~ 19。範例一:用 root 讓原本的 nice 再減少 5 (-5),用於執行 vim ,並觀察該程序!
nice -n -5 vim &
[1] 19865
ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 14836 14835 0 90 10 - 29068 wait pts/0 00:00:00 bash
4 T 0 19865 14836 0 85 5 - 37757 signal pts/0 00:00:00 vim
0 R 0 19866 14836 0 90 10 - 30319 - pts/0 00:00:00 ps
# 原本的 bash PRI 為 90 ,所以 vim 預設應為 90。不過由於給予 nice 為 -5 ,
# 因此 vim 的 PRI 降低了!RPI 與 NI 各減 5 !但不一定每次都是正好相同喔!因為核心會動態調整
kill -9 %1 <==測試完畢將 vim 關閉
就如同前面說的, nice 是用來調整程序的執行優先順序!這裡只是一個執行的範例罷了! 通常什麼時候要將 nice 值調大呢?舉例來說,系統的背景工作中, 某些比較不重要的程序之進行:例如備份工作!由於備份工作相當的耗系統資源, 這個時候就可以將備份的指令之 nice 值調大一些,可以使系統的資源分配的更為公平!
另外,『 nice -n N command 』那個 N 指的是『在原本的 nice 值底下,再加上的一個值,變成新的 nice 值』之意。 所以在上面的範例中,原本的 nice 為 10,使用了 nice -n -5 之後,就會變成 (10+(-5)),最終結果就是 5 囉! 並不是直接指定 nice 值喔!
renice :已存在程序的 nice 重新調整
renice
renice [number] PID
選項與參數:
PID :某個程序的 ID 啊!範例一:找出自己的 bash PID ,並將該 PID 的 nice 調整到 -5
ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 14836 14835 0 90 10 - 29068 wait pts/0 00:00:00 bash
0 R 0 19900 14836 0 90 10 - 30319 - pts/0 00:00:00 ps
renice -5 14836
14836 (process ID) old priority 10, new priority -5
ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 14836 14835 0 75 -5 - 29068 wait pts/0 00:00:00 bash
0 R 0 19910 14836 0 75 -5 - 30319 - pts/0 00:00:00 ps
如果要調整的是已經存在的某個程序的話,那麼就得要使用 renice 了。使用的方法很簡單, renice 後面接上數值及 PID 即可。因為後面接的是 PID ,所以你務必要以 ps 或者其他程序觀察的指令去找出 PID 才行啊!
由上面這個範例當中我們也看的出來,雖然修改的是 bash 那個程序,但是該程序所觸發的 ps 指令當中的 nice 也會繼承而為 -5 喔!瞭解了吧!整個 nice 值是可以在父程序 --> 子程序之間傳遞的呢! 另外,除了 renice 之外,其實那個 top 同樣的也是可以調整 nice 值的!
系統資源的觀察
除了系統的程序之外,我們還必須就系統的一些資源進行檢查啊!舉例來說,我們使用 top 可以看到很多系統的資源對吧!那麼,還有沒有其他的工具可以查閱的? 當然有啊!底下這些工具指令可以玩一玩!
free :觀察記憶體使用情況
free
free [-b|-k|-m|-g|-h] [-t] [-s N -c N]
選項與參數:
-b :直接輸入 free 時,顯示的單位是 Kbytes,我們可以使用 b(bytes), m(Mbytes)
k(Kbytes), 及 g(Gbytes) 來顯示單位喔!也可以直接讓系統自己指定單位 (-h)
-t :在輸出的最終結果,顯示實體記憶體與 swap 的總量。
-s :可以讓系統每幾秒鐘輸出一次,不間斷的一直輸出的意思!對於系統觀察挺有效!
-c :與 -s 同時處理~讓 free 列出幾次的意思~範例一:顯示目前系統的記憶體容量
free -m
total used free shared buff/cache available
Mem: 2848 346 1794 8 706 2263
Swap: 1023 0 1023
uname:查閱系統與核心相關資訊
uname
uname [-asrmpi]
選項與參數:
-a :所有系統相關的資訊,包括底下的資料都會被列出來;
-s :系統核心名稱
-r :核心的版本
-m :本系統的硬體名稱,例如 i686 或 x86_64 等;
-p :CPU 的類型,與 -m 類似,只是顯示的是 CPU 的類型!
-i :硬體的平台 (ix86)範例一:輸出系統的基本資訊
uname -a
Linux study.centos.vbird 3.10.0-229.el7.x86_64 #1 SMP Fri Mar 6 11:36:42 UTC 2015
x86_64 x86_64 x86_64 GNU/Linux
uptime 觀察系統啟動時間與工作負載
這個指令很單純呢!就是顯示出目前系統已經開機多久的時間,以及 1, 5, 15 分鐘的平均負載就是了。uptime 可以顯示出 top 畫面的最上面一行。
uptime
02:35:27 up 7:48, 3 users, load average: 0.00, 0.01, 0.05
#top 這個指令已經談過相關資訊,不再聊!
netstat 追蹤網路或插槽檔
這個 netstat 也是挺好玩的,其實這個指令比較常被用在網路的監控方面,不過,在程序管理方面也是需要瞭解的啦! 這個指令的執行如下所示:基本上, netstat 的輸出分為兩大部分,分別是網路與系統自己的程序相關性部分:
netstat
netstat -[atunlp]
選項與參數:
-a :將目前系統上所有的連線、監聽、Socket 資料都列出來
-t :列出 tcp 網路封包的資料
-u :列出 udp 網路封包的資料
-n :不以程序的服務名稱,以埠號 (port number) 來顯示;
-l :列出目前正在網路監聽 (listen) 的服務;
-p :列出該網路服務的程序 PID範例一:列出目前系統已經建立的網路連線與 unix socket 狀態
netstatActive Internet connections (w/o servers) <==與網路較相關的部分
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 172.16.15.100:ssh 172.16.220.234:48300 ESTABLISHED
Active UNIX domain sockets (w/o servers) <==與本機的程序自己的相關性(非網路)
Proto RefCnt Flags Type State I-Node Path
unix 2 [ ] DGRAM 1902 @/org/freedesktop/systemd1/notify
unix 2 [ ] DGRAM 1944 /run/systemd/shutdownd
....(中間省略)....
unix 3 [ ] STREAM CONNECTED 25425 @/tmp/.X11-unix/X0
unix 3 [ ] STREAM CONNECTED 28893
unix 3 [ ] STREAM CONNECTED 21262
在上面的結果當中,顯示了兩個部分,分別是網路的連線以及 linux 上面的 socket 程序相關性部分。 我們先來看看網際網路連線情況的部分
項目 | 描述 |
---|---|
Proto | 網路的封包協定,主要分為 TCP 與 UDP 封包 |
Recv-Q | 非由使用者程式連結到此 socket 的複製的總 bytes 數 |
Send-Q | 非由遠端主機傳送過來的 acknowledged 總 bytes 數 |
Local Address | 本地端的 IP:port 情況 |
Foreign Address | 遠端主機的 IP:port 情況 |
State | 連線狀態,主要有建立(ESTABLISED)及監聽(LISTEN) |
我們看上面僅有一條連線的資料,他的意義是:『透過 TCP 封包的連線,遠端 的 172.16.220.234:48300 連線到本地端的 172.16.15.100:ssh ,這條連線狀態是建立 (ESTABLISHED) 的狀態!』至於更多的網路環境說明, 就得到鳥哥的另一本伺服器篇查閱囉!
除了網路上的連線之外,其實 Linux 系統上面的程序是可以接收不同程序所發送來的資訊,那就是 Linux 上頭的插槽檔 (socket file)。我們在第五章的檔案種類有稍微提到 socket 檔案, 但當時未談到程序的概念,所以沒有深入談論。socket file 可以溝通兩個程序之間的資訊,因此程序可以取得對方傳送過來的資料。 由於有 socket file,因此類似 X Window 這種需要透過網路連接的軟體,目前新版的 distributions 就以 socket 來進行視窗介面的連線溝通了。上表中 socket file 的輸出欄位有:
項目 | 描述 |
---|---|
Proto | 一般就是 unix |
RefCnt | 連接到此 socket 的程序數量 |
Flags | 連線的旗標 |
Type | socket 存取的類型。主要有確認連線的 STREAM 與不需確認的 DGRAM 兩種 |
State | 若為 CONNECTED 表示多個程序之間已經連線建立 |
Path | 連接到此 socket 的相關程式的路徑!或者是相關資料輸出的路徑 |
以上表的輸出為例,最後那三行在 /tmp/.xx 底下的資料,就是 X Window 視窗介面的相關程序啦! 而 PATH 指向的就是這些程序要交換資料的插槽檔案囉!好!那麼 netstat 可以幫我們進行什麼任務呢? 很多喔!我們先來看看,利用 netstat 去看看我們的哪些程序有啟動哪些網路的『後門』呢?
範例二:找出目前系統上已在監聽的網路連線及其 PID
netstat -tulnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1326/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 2349/master
tcp6 0 0 :::22 :::* LISTEN 1326/sshd
tcp6 0 0 ::1:25 :::* LISTEN 2349/master
udp 0 0 0.0.0.0:123 0.0.0.0:* 751/chronyd
udp 0 0 127.0.0.1:323 0.0.0.0:* 751/chronyd
udp 0 0 0.0.0.0:57808 0.0.0.0:* 743/avahi-daemon: r
udp 0 0 0.0.0.0:5353 0.0.0.0:* 743/avahi-daemon: r
udp6 0 0 :::123 :::* 751/chronyd
udp6 0 0 ::1:323 :::* 751/chronyd
# 除了可以列出監聽網路的介面與狀態之外,最後一個欄位還能夠顯示此服務的
# PID 號碼以及程序的指令名稱喔!例如上頭的 1326 就是該 PID範例三:將上述的 0.0.0.0:57808 那個網路服務關閉的話?
kill -9 743
killall -9 avahi-daemon
dmesg 分析核心產生的訊息
系統在開機的時候,核心會去偵測系統的硬體,你的某些硬體到底有沒有被捉到,那就與這個時候的偵測有關。 但是這些偵測的過程要不是沒有顯示在螢幕上,就是很飛快的在螢幕上一閃而逝!能不能把核心偵測的訊息捉出來瞧瞧? 可以的,那就使用 dmesg 吧!
所有核心偵測的訊息,不管是開機時候還是系統運作過程中,反正只要是核心產生的訊息,都會被記錄到記憶體中的某個保護區段。 dmesg 這個指令就能夠將該區段的訊息讀出來的!因為訊息實在太多了,所以執行時可以加入這個管線指令『 | more 』來使畫面暫停!
dmesg
範例一:輸出所有的核心開機時的資訊
dmesg | more範例二:搜尋開機的時候,硬碟的相關資訊為何?
dmesg | grep -i vda
[ 0.758551] vda: vda1 vda2 vda3 vda4 vda5 vda6 vda7 vda8 vda9
[ 3.964134] XFS (vda2): Mounting V4 Filesystem
....(底下省略)....
vmstat 偵測系統資源變化
如果你想要動態的瞭解一下系統資源的運作,那麼這個 vmstat 確實可以玩一玩!vmstat 可以偵測『 CPU / 記憶體 / 磁碟輸入輸出狀態 』等等,如果你想要瞭解一部繁忙的系統到底是哪個環節最累人, 可以使用 vmstat 分析看看。底下是常見的選項與參數說明:
vmstat
vmstat [-a] [延遲 [總計偵測次數]] <==CPU/記憶體等資訊
vmstat [-fs] <==記憶體相關
vmstat [-S 單位] <==設定顯示數據的單位
vmstat [-d] <==與磁碟有關
vmstat [-p 分割槽] <==與磁碟有關
選項與參數:
-a :使用 inactive/active(活躍與否) 取代 buffer/cache 的記憶體輸出資訊;
-f :開機到目前為止,系統複製 (fork) 的程序數;
-s :將一些事件 (開機至目前為止) 導致的記憶體變化情況列表說明;
-S :後面可以接單位,讓顯示的資料有單位。例如 K/M 取代 bytes 的容量;
-d :列出磁碟的讀寫總量統計表
-p :後面列出分割槽,可顯示該分割槽的讀寫總量統計表範例一:統計目前主機 CPU 狀態,每秒一次,共計三次!
vmstat 1 3
procs ------------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 1838092 1504 722216 0 0 4 1 6 9 0 0 100 0 0
0 0 0 1838092 1504 722200 0 0 0 0 13 23 0 0 100 0 0
0 0 0 1838092 1504 722200 0 0 0 0 25 46 0 0 100 0 0
利用 vmstat 甚至可以進行追蹤喔!你可以使用類似『 vmstat 5 』代表每五秒鐘更新一次,且無窮的更新!直到你按下 [ctrl]-c 為止。如果你想要即時的知道系統資源的運作狀態,這個指令就不能不知道!
項目 | 描述 |
---|---|
程序欄位 (procs) | r :等待運作中的程序數量;b:不可被喚醒的程序數量。這兩個項目越多,代表系統越 忙碌 (因為系統太忙,所以很多程序就無法被執行或一直在等待而無法被喚醒之故)。 |
記憶體欄位 (memory) | swpd:虛擬記憶體被使用的容量; free:未被使用的記憶體容量; buff:用於緩衝記憶體; cache:用於快取記憶體。 這部份則與 free 是相同的。 |
記憶體置換空間 (swap) | si:由磁碟中將程序取出的量; so:由於記憶體不足而將沒用到的程序寫入到磁碟的 swap 的容量。 如果 si/so 的數值太大,表示記憶體內的資料常常得在磁碟與主記憶體之間傳來傳去,系統效能會很差 |
磁碟讀寫 (io) | bi:由磁碟讀入的區塊數量; bo:寫入到磁碟去的區塊數量。如果這部份的值越高,代表系統的 I/O 非常忙碌 |
系統 (system) | in:每秒被中斷的程序次數; cs:每秒鐘進行的事件切換次數;這兩個數值越大,代表系統與周邊設備的溝通非常頻繁! 這些周邊設備當然包括磁碟、網路卡、時間鐘等。 |
CPU | us:非核心層的 CPU 使用狀態; sy:核心層所使用的 CPU 狀態; id:閒置的狀態; wa:等待 I/O 所耗費的 CPU 狀態; st:被虛擬機器 (virtual machine) 所盜用的 CPU 使用狀態 (2.6.11 以後才支援) |
範例二:系統上面所有的磁碟的讀寫狀態
vmstat -d
disk- ------------reads------------ ------------writes----------- -----IO------
total merged sectors ms total merged sectors ms cur sec
vda 21928 0 992587 47490 7239 2225 258449 13331 0 26
sda 395 1 3168 213 0 0 0 0 0 0
sr0 0 0 0 0 0 0 0 0 0 0
dm-0 19139 0 949575 44608 7672 0 202251 16264 0 25
dm-1 336 0 2688 327 0 0 0 0 0 0
md0 212 0 1221 0 14 0 4306 0 0 0
dm-2 218 0 9922 565 54 0 4672 128 0 0
dm-3 179 0 957 182 11 0 4306 68 0 0
詳細的各欄位就請諸位大德查閱一下 man vmstat 囉!反正與讀寫有關啦!這樣瞭解乎!
特殊檔案與程序
我們在第六章曾經談到特殊權限的 SUID/SGID/SBIT ,雖然第六章已經將這三種特殊權限作了詳細的解釋,不過,我們依舊要來探討的是,那麼到底這些權限對於你的『程序』是如何影響的? 此外,程序可能會使用到系統資源,舉例來說,磁碟就是其中一項資源。哪天你在 umount 磁碟時,系統老是出現『 device is busy 』的字樣~到底是怎麼回事啊?我們底下就來談一談這些和程序有關係的細節部分:
具有 SUID/SGID 權限的指令執行狀態
SUID 的權限其實與程序的相關性非常的大!為什麼呢?先來看看 SUID 的程式是如何被一般使用者執行,且具有什麼特色呢?
- SUID 權限僅對二進位程式(binary program)有效;
- 執行者對於該程式需要具有 x 的可執行權限;
- 本權限 僅在執行該程式的過程中有效 (run-time);
- 執行者將具有該程式擁有者 (owner) 的權限。
所以說,整個 SUID 的權限會生效是由於『具有該權限的程式被觸發』,而我們知道一個程式被觸發會變成程序, 所以囉,執行者可以具有程式擁有者的權限就是在該程式變成程序的那個時候啦!第六章我們還沒談到程序的概念, 所以你或許那時候會覺得很奇怪,為啥執行了 passwd 後你就具有 root 的權限呢?不都是一般使用者執行的嗎? 這是因為你在觸發 passwd 後,會取得一個新的程序與 PID,該 PID 產生時透過 SUID 來給予該 PID 特殊的權限設定啦! 我們使用 dmtsai 登入系統且執行 passwd 後,透過工作控制來理解一下!
[dmtsai@study ~]$passwd
Changing password for user dmtsai.
Changing password for dmtsai
(current) UNIX password: <==這裡按下 [ctrl]-z 並且按下 [enter]
[1]+ Stopped passwd
[dmtsai@study ~]$pstree -uA
systemd-+-ModemManager---2*[{ModemManager}]
....(中間省略)....
|-sshd---sshd---sshd(dmtsai)---bash-+-passwd(root)
| `-pstree
....(底下省略)....
從上表的結果我們可以發現,底線的部分是屬於 dmtsai 這個一般帳號的權限,特殊字體的則是 root 的權限! 但你看到了, passwd 確實是由 bash 衍生出來的!不過就是權限不一樣!透過這樣的解析, 你也會比較清楚為何不同程式所產生的權限不同了吧!這是由於『SUID 程式運作過程中產生的程序』的關係啦!
那麼既然 SUID/SGID 的權限是比較可怕的,您該如何查詢整個系統的 SUID/SGID 的檔案呢? 應該是還不會忘記吧?使用 find 即可啊!
find / -perm /6000
/proc/* 代表的意義
其實,我們之前提到的所謂的程序都是在記憶體當中嘛!而記憶體當中的資料又都是寫入到 /proc/* 這個目錄下的,所以囉,我們當然可以直接觀察 /proc 這個目錄當中的檔案啊! 如果你觀察過 /proc 這個目錄的話,應該會發現他有點像這樣:
ll /proc
dr-xr-xr-x. 8 root root 0 Aug 4 18:46 1
dr-xr-xr-x. 8 root root 0 Aug 4 18:46 10
dr-xr-xr-x. 8 root root 0 Aug 4 18:47 10548
....(中間省略)....
-r--r--r--. 1 root root 0 Aug 5 17:48 uptime
-r--r--r--. 1 root root 0 Aug 5 17:48 version
-r--------. 1 root root 0 Aug 5 17:48 vmallocinfo
-r--r--r--. 1 root root 0 Aug 5 17:48 vmstat
-r--r--r--. 1 root root 0 Aug 5 17:48 zoneinfo
基本上,目前主機上面的各個程序的 PID 都是以目錄的型態存在於 /proc 當中。 舉例來說,我們開機所執行的第一支程式 systemd 他的 PID 是 1 , 這個 PID 的所有相關資訊都寫入在 /proc/1/* 當中!若我們直接觀察 PID 為 1 的資料好了,他有點像這樣:
ll /proc/1
dr-xr-xr-x. 2 root root 0 Aug 4 19:25 attr
-rw-r--r--. 1 root root 0 Aug 4 19:25 autogroup
-r--------. 1 root root 0 Aug 4 19:25 auxv
-r--r--r--. 1 root root 0 Aug 4 18:46 cgroup
--w-------. 1 root root 0 Aug 4 19:25 clear_refs
-r--r--r--. 1 root root 0 Aug 4 18:46 cmdline <==就是指令串
-r--------. 1 root root 0 Aug 4 18:46 environ <==一些環境變數
lrwxrwxrwx. 1 root root 0 Aug 4 18:46 exe
....(以下省略)....
裡面的資料還挺多的,不過,比較有趣的其實是兩個檔案,分別是:
- cmdline:這個程序被啟動的指令串;
- environ:這個程序的環境變數內容。
很有趣吧!如果你查閱一下 cmdline 的話,就會發現:
cat /proc/1/cmdline
/usr/lib/systemd/systemd--switched-root--system--deserialize24
就是這個指令、選項與參數啟動 systemd 的啦!這還是跟某個特定的 PID 有關的內容呢,如果是針對整個 Linux 系統相關的參數呢?那就是在 /proc 目錄底下的檔案啦!相關的檔案與對應的內容是這樣的: (註3)
檔名 | 檔案內容 |
---|---|
/proc/cmdline | 載入 kernel 時所下達的相關指令與參數!查閱此檔案,可瞭解指令是如何啟動的! |
/proc/cpuinfo | 本機的 CPU 的相關資訊,包含時脈、類型與運算功能等 |
/proc/devices | 這個 檔案記錄了系統各個主要裝置的主要裝置代號,與 https://linux.vbird.org/linux_basic/0230filesystem.php#mknod 有關呢! |
/proc/filesystems | 目前系統已經載入的檔案系統囉! |
/proc/interrupts | 目前系統上面的 IRQ 分配狀態。 |
/proc/ioports | 目前系統上面各個裝置所配置的 I/O 位址。 |
/proc/kcore | 這個就是記憶體的大小啦!好大對吧!但是不要讀他啦! |
/proc/loadavg | 還記得 https://linux.vbird.org/linux_basic/centos7/0440processcontrol.php#topm 以及 https://linux.vbird.org/linux_basic/centos7/0440processcontrol.php#uptime 吧?沒錯!上頭的三個平均數值就是記錄在此! |
/proc/meminfo | 使用 https://linux.vbird.org/linux_basic/centos7/0440processcontrol.php#free 列出的記憶體資訊,嘿嘿!在這裡也能夠查閱到! |
/proc/modules | 目前我們的 Linux 已經載入的模組列表,也可以想成是驅動程式啦! |
/proc/mounts | 系統已經掛載的資料,就是用 mount 這個指令呼叫出來的資料啦! |
/proc/swaps | 到底系統掛載入的記憶體在哪裡?呵呵!使用掉的 partition 就記錄在此啦! |
/proc/partitions | 使用 fdisk -l 會出現目前所有的 partition 吧?在這個檔案當中也有紀錄喔! |
/proc/uptime | 就是用 uptime 的時候,會出現的資訊啦! |
/proc/version | 核心的版本,就是用 uname -a 顯示的內容啦! |
/proc/bus/* | 一些匯流排的裝置,還有 USB 的裝置也記錄在此喔! |
其實,上面這些檔案鳥哥在此建議您可以使用 cat 去查閱看看,不必深入瞭解, 不過,觀看過檔案內容後,畢竟會比較有感覺啦!如果未來您想要自行撰寫某些工具軟體, 那麼這個目錄底下的相關檔案可能會對您有點幫助的喔!
查詢已開啟檔案或已執行程序開啟之檔案
其實還有一些與程序相關的指令可以值得參考與應用的,我們來談一談:
fuser 藉由檔案(或檔案系統)找出正在使用該檔案的程序
有的時候我想要知道我的程序到底在這次啟動過程中開啟了多少檔案,可以利用 fuser 來觀察啦! 舉例來說,你如果卸載時發現系統通知:『 device is busy 』,那表示這個檔案系統正在忙碌中, 表示有某支程序有利用到該檔案系統啦!那麼你就可以利用 fuser 來追蹤囉!fuser 語法有點像這樣:
fuser
fuser [-umv] [-k [i] [-signal]] file/dir
選項與參數:
-u :除了程序的 PID 之外,同時列出該程序的擁有者;
-m :後面接的那個檔名會主動的上提到該檔案系統的最頂層,對 umount 不成功很有效!
-v :可以列出每個檔案與程序還有指令的完整相關性!
-k :找出使用該檔案/目錄的 PID ,並試圖以 SIGKILL 這個訊號給予該 PID;
-i :必須與 -k 配合,在刪除 PID 之前會先詢問使用者意願!
-signal:例如 -1 -15 等等,若不加的話,預設是 SIGKILL (-9) 囉!範例一:找出目前所在目錄的使用 PID/所屬帳號/權限 為何?
fuser -uv .
USER PID ACCESS COMMAND
/root: root 13888 ..c.. (root)bash
root 31743 ..c.. (root)bash
看到輸出的結果沒?他說『.』底下有兩個 PID 分別為 13888, 31743 的程序,該程序屬於 root 且指令為 bash 。 比較有趣的是那個 ACCESS 的項目,那個項目代表的意義為:
- c :此程序在當前的目錄下(非次目錄);
- e :可被觸發為執行狀態;
- f :是一個被開啟的檔案;
- r :代表頂層目錄 (root directory);
- F :該檔案被開啟了,不過在等待回應中;
- m :可能為分享的動態函式庫;
那如果你想要查閱某個檔案系統底下有多少程序正在佔用該檔案系統時,那個 -m 的選項就很有幫助了! 讓我們來做幾個簡單的測試,包括實體的檔案系統掛載與 /proc 這個虛擬檔案系統的內容, 看看有多少的程序對這些掛載點或其他目錄的使用狀態吧!
範例二:找到所有使用到 /proc 這個檔案系統的程序吧!
fuser -uv /proc
/proc: root kernel mount (root)/proc
rtkit 768 .rc.. (rtkit)rtkit-daemon
# 資料量還不會很多,雖然這個目錄很繁忙~沒關係!我們可以繼續這樣作,看看其他的程序!
fuser -mvu /proc
USER PID ACCESS COMMAND
/proc: root kernel mount (root)/proc
root 1 f.... (root)systemd
root 2 ...e. (root)kthreadd
.....(底下省略).....# 有這幾支程序在進行 /proc 檔案系統的存取喔!這樣清楚了嗎?範例三:找到所有使用到 /home 這個檔案系統的程序吧!
echo $$
31743 # 先確認一下,自己的 bash PID 號碼吧!
cd /home
[root@study home]#fuser -muv .
USER PID ACCESS COMMAND
/home: root kernel mount (root)/home
dmtsai 31535 ..c.. (dmtsai)bash
root 31571 ..c.. (root)passwd
root 31737 ..c.. (root)sudo
root 31743 ..c.. (root)bash # 果然,自己的 PID 在啊!
[root@study home]#cd ~
umount /home
umount: /home: target is busy.
(In some cases useful info about processes that use
the device is found by lsof(8) or fuser(1))
# 從 fuser 的結果可以知道,總共有五隻 process 在該目錄下運作,那即使 root 離開了 /home,
# 當然還是無法 umount 的!那要怎辦?哈哈!可以透過如下方法一個一個刪除~
fuser -mki /home
/home: 31535c 31571c 31737c # 你會發現, PID 跟上面查到的相同!
Kill process 31535 ? (y/N) # 這裡會問你要不要刪除!當然不要亂刪除啦!通通取消!
既然可以針對整個檔案系統,那麼能不能僅針對單一檔案啊?當然可以囉!看一下底下的案例先:
範例四:找到 /run 底下屬於 FIFO 類型的檔案,並且找出存取該檔案的程序
find /run -type p.....(前面省略).....
/run/systemd/sessions/165.ref
/run/systemd/sessions/1.ref
/run/systemd/sessions/c1.ref # 隨便抓個項目!就是這個好了!來測試一下!
fuser -uv /run/systemd/sessions/c1.ref
USER PID ACCESS COMMAND
/run/systemd/sessions/c1.ref:
root 763 f.... (root)systemd-logind
root 5450 F.... (root)gdm-session-wor
# 通常系統的 FIFO 檔案都會放置到 /run 底下,透過這個方式來追蹤該檔案被存取的 process!
# 也能夠曉得系統有多忙碌啊!呵呵!
如何?很有趣的一個指令吧!透過這個 fuser 我們可以找出使用該檔案、目錄的程序,藉以觀察的啦! 他的重點與 ps, pstree 不同。 fuser 可以讓我們瞭解到某個檔案 (或檔案系統) 目前正在被哪些程序所利用!
lsof 列出被程序所開啟的檔案檔名
相對於 fuser 是由檔案或者裝置去找出使用該檔案或裝置的程序,反過來說,如何查出某個程序開啟或者使用的檔案與裝置呢?呼呼!那就是使用 lsof 囉~
lsof
lsof [-aUu] [+d]選項與參數:
-a :多項資料需要『同時成立』才顯示出結果時!
-U :僅列出 Unix like 系統的 socket 檔案類型;
-u :後面接 username,列出該使用者相關程序所開啟的檔案;
+d :後面接目錄,亦即找出某個目錄底下已經被開啟的檔案!範例一:列出目前系統上面所有已經被開啟的檔案與裝置:
lsof
COMMAND PID TID USER FD TYPE DEVICE SIZE/OFF NODE NAME
systemd 1 root cwd DIR 253,0 4096 128 /
systemd 1 root rtd DIR 253,0 4096 128 /
systemd 1 root txt REG 253,0 1230920 967763 /usr/lib/systemd/systemd
....(底下省略)....# 注意到了嗎?是的,在預設的情況下, lsof 會將目前系統上面已經開啟的
# 檔案全部列出來~所以,畫面多的嚇人啊!您可以注意到,第一個檔案 systemd 執行的
# 地方就在根目錄 ,而根目錄,嘿嘿!所在的 inode 也有顯示出來喔!範例二:僅列出關於 root 的所有程序開啟的 socket 檔案
lsof -u root -a -U
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
systemd 1 root 3u unix 0xffff8800b7756580 0t0 13715 socket
systemd 1 root 7u unix 0xffff8800b7755a40 0t0 1902 @/org/freedesktop/systemd1/notify
systemd 1 root 9u unix 0xffff8800b7756d00 0t0 1903 /run/systemd/private
.....(中間省略).....
Xorg 4496 root 1u unix 0xffff8800ab107480 0t0 25981 @/tmp/.X11-unix/X0
Xorg 4496 root 3u unix 0xffff8800ab107840 0t0 25982 /tmp/.X11-unix/X0
Xorg 4496 root 16u unix 0xffff8800b7754f00 0t0 25174 @/tmp/.X11-unix/X0
.....(底下省略).....# 注意到那個 -a 吧!如果你分別輸入 lsof -u root 及 lsof -U ,會有啥資訊?
# 使用 lsof -u root -U 及 lsof -u root -a -U ,呵呵!都不同啦!
# -a 的用途就是在解決同時需要兩個項目都成立時啊! ^_^範例三:請列出目前系統上面所有的被啟動的周邊裝置
lsof +d /dev
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
systemd 1 root 0u CHR 1,3 0t0 1028 /dev/null
systemd 1 root 1u CHR 1,3 0t0 1028 /dev/null
# 看吧!因為裝置都在 /dev 裡面嘛!所以囉,使用搜尋目錄即可啊!範例四:秀出屬於 root 的 bash 這支程式所開啟的檔案
lsof -u root | grep bash
ksmtuned 781 root txt REG 253,0 960384 33867220 /usr/bin/bash
bash 13888 root cwd DIR 253,0 4096 50331777 /root
bash 13888 root rtd DIR 253,0 4096 128 /
bash 13888 root txt REG 253,0 960384 33867220 /usr/bin/bash
bash 13888 root mem REG 253,0 106065056 17331169 /usr/lib/locale/locale-archive
....(底下省略)....
pidof 找出某支正在執行的程式的 PID
pidof
pidof [-sx] program_name選項與參數:
-s :僅列出一個 PID 而不列出所有的 PID
-x :同時列出該 program name 可能的 PPID 那個程序的 PID範例一:列出目前系統上面 systemd 以及 rsyslogd 這兩個 程式的 PID
pidof systemd rsyslogd
1 742
# 理論上,應該會有兩個 PID 才對。上面的顯示也是出現了兩個 PID 喔。
# 分別是 systemd 及 rsyslogd 這兩支程式的 PID 啦。
很簡單的用法吧,透過這個 pidof 指令,並且配合 ps aux 與正規表示法,就可以很輕易的找到您所想要的程序內容了呢。 如果要找的是 bash ,那就 pidof bash ,立刻列出一堆 PID 號碼了。
SELinux 初探
什麼是 SELinux 呢?其實他是『 Security Enhanced Linux 』的縮寫,字面上的意義就是安全強化的 Linux 之意!
傳統的檔案權限與帳號關係:自主式存取控制, DAC
我們第十三章的內容,知道系統的帳號主要分為系統管理員 (root) 與一般用戶,而這兩種身份能否使用系統上面的檔案資源則與 rwx 的權限設定有關。 不過你要注意的是,各種權限設定對 root 是無效的。因此,當某個程序想要對檔案進行存取時, 系統就會根據該程序的擁有者/群組,並比對檔案的權限,若通過權限檢查,就可以存取該檔案了。
這種存取檔案系統的方式被稱為『自主式存取控制 (Discretionary Access Control, DAC)』,基本上,就是依據程序的擁有者與檔案資源的 rwx 權限來決定有無存取的能力。 不過這種 DAC 的存取控制有幾個困擾,那就是:
- root 具有最高的權限:如果不小心某支程序被有心人士取得, 且該程序屬於 root 的權限,那麼這支程序就可以在系統上進行任何資源的存取!真是要命!
- 使用者可以取得程序來變更檔案資源的存取權限:如果你不小心將某個目錄的權限設定為 777 ,由於對任何人的權限會變成 rwx ,因此該目錄就會被任何人所任意存取!
這些問題是非常嚴重的!尤其是當你的系統是被某些漫不經心的系統管理員所掌控時!她們甚至覺得目錄權限調為 777 也沒有什麼了不起的危險哩...